import os
import re
from datetime import datetime, timedelta
import tkinter as tk
from tkinter import filedialog
import pandas as pd
from collections import defaultdict

def select_input_file_path():
    """选择输入日志文件"""
    root = tk.Tk()
    root.withdraw()
    return filedialog.askopenfilename(
        title="选择日志文件",
        filetypes=[("Log files", "*.txt"), ("All files", "*.*")]
    )

def select_output_file_path():
    """选择输出Excel文件路径"""
    root = tk.Tk()
    root.withdraw()
    return filedialog.asksaveasfilename(
        defaultextension=".xlsx",
        filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")]
    )

def generate_time_intervals(start, end, interval):
    """生成时间区间列表"""
    intervals = []
    current = start
    while current < end:
        next_time = current + timedelta(minutes=interval)
        intervals.append((current, min(next_time, end)))
        current = next_time
    return intervals

def process_logs(file_path, time_intervals):
    """处理日志文件并返回统计结果"""
    # 预编译正则表达式
    timestamp_pat = re.compile(r'\[(\d{2}:\d{2}:\d{2}\.\d{3})\]')
    correct_pat = re.compile(r'^\[\d{2}:\d{2}:\d{2}\.\d{3}\].*?=\d+\.\d{2}.*$')
    est_pat = re.compile(r'est\[[^\]]+\]')
    node_pat = re.compile(r'(?P<hex>[0-9A-Fa-f]{4})\[(?P<coords>(\d+\.\d{2},){2}\d+\.\d{2})\]=(?P<result>\d+\.\d{2})')

    stats = defaultdict(lambda: defaultdict(int))

    try:
        with open(file_path, 'r', encoding='GB2312', errors='replace') as file:
            current_block = ""
            for line in file:
                line = line.replace('收←◆', '').strip()
                
                if not line:  # 遇到空行处理块
                    if current_block:
                        process_single_block(
                            current_block, stats, time_intervals,
                            timestamp_pat, correct_pat, est_pat, node_pat
                        )
                    current_block = ""
                else:
                    current_block += line

            # 处理最后一个块
            if current_block:
                process_single_block(
                    current_block, stats, time_intervals,
                    timestamp_pat, correct_pat, est_pat, node_pat
                )

    except Exception as e:
        print(f"文件处理错误: {e}")

    # 转换为DataFrame
    return convert_stats_to_dataframe(stats)

def process_single_block(block, stats, intervals, 
                        ts_pat, valid_pat, est_pat, node_pat):
    """处理单个日志块并更新统计信息"""
    # 提取第一个时间戳
    ts_match = ts_pat.search(block)
    if not ts_match:
        return

    # 构造完整时间对象
    try:
        log_time = datetime.strptime(ts_match.group(1), "%H:%M:%S.%f").replace(
            year=intervals[0][0].year,
            month=intervals[0][0].month,
            day=intervals[0][0].day
        )
    except ValueError:
        return

    # 验证块格式有效性
    cleaned_block = ts_pat.sub('', block)  # 仅移除第一个时间戳
    cleaned_block = f"[{ts_match.group(1)}]{cleaned_block.replace(' ', '')}"
    
    if not valid_pat.match(cleaned_block):
        return

    # 确定所属时间区间
    for start, end in intervals:
        if start <= log_time < end:
            time_label = f"{start.strftime('%Y-%m-%d %H:%M:%S')} - {end.strftime('%H:%M:%S')}"
            
            if est_pat.search(cleaned_block):
                stats[time_label]['est'] += 1
            else:
                conn_count = len(node_pat.findall(cleaned_block))
                stats[time_label][conn_count] += 1
            break

def convert_stats_to_dataframe(stats):
    """将统计字典转换为DataFrame"""
    print(stats)
    data = []
    for time_range, counts in stats.items():
        row = {"时间区间": time_range}
        for category, count in counts.items():
            row[str(category)] = count
        data.append(row)
    # 转换为DataFrame
    df = pd.DataFrame(data)
    numeric_columns = sorted((col for col in df.columns if col.isdigit() or col == "est"), key=lambda x: (x != "est", int(x) if x.isdigit() else float('inf')))
    other_columns = [col for col in df.columns if col not in numeric_columns and col != "时间区间"]
    sorted_columns = ["时间区间"] + numeric_columns + other_columns
    
    # 注意：如果 "est" 应该始终排在数字之前，可以调整排序逻辑
    # 例如，可以使用一个更明确的规则来确定 "est" 的位置
    
    return df[sorted_columns].fillna(0)

def main():
    # 配置时间参数（根据实际日志日期调整）
    start_time = datetime(2025, 2, 27, 10, 30, 37)
    end_time = datetime(2025, 2, 27, 11, 10, 37)
    interval = 2  # 分钟

    # 文件选择
    input_path = select_input_file_path()
    if not input_path:
        print("未选择输入文件")
        return

    output_path = select_output_file_path()
    if not output_path:
        print("未选择输出文件")
        return

    # 生成时间区间
    time_ranges = generate_time_intervals(start_time, end_time, interval)

    # 处理日志并保存结果
    result_df = process_logs(input_path, time_ranges)
    if not result_df.empty:
        result_df.to_excel(output_path, index=False)
        print(f"结果已保存至: {output_path}")
    else:
        print("未找到有效日志数据")

if __name__ == "__main__":
    main()